package org.ns.framework.datasource.config;


import org.ns.framework.datasource.mybatis.DataSourceServiceInjector;
import org.ns.framework.datasource.mybatis.MybatisDataSourceInjector;
import org.ns.framework.datasource.mybatis.MybatisMapperManage;
import org.ns.framework.datasource.redis.RedisBeanInjector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DataSourceConfiguration implements InitializingBean, ApplicationContextAware {

    private ApplicationContext applicationContext;

	private static final Logger log = LoggerFactory.getLogger(DataSourceConfiguration.class);

    @Bean
    DataSourceConfig dataSourceConfig() {
        return new DataSourceConfig();
    }

    @Bean
    RedisBeanInjector redisBeanInjector() {
        return new RedisBeanInjector();
    }

    @Bean
    MybatisDataSourceInjector mybatisDataSourceInjector() {
        return new MybatisDataSourceInjector();
    }

    @Bean
    MybatisConfigurationManage mybatisConfigurationManage() {
    	return new MybatisConfigurationManage();
    };

    @Bean
    MybatisMapperManage mybatisMapperManage() {
    	return new MybatisMapperManage();
    }
    @Bean
    DataSourceServiceInjector dataSourceServiceInjector() {
    	return new DataSourceServiceInjector();
    }
    @Bean
    DataSourceLoader dataSourceLoader() {
    	return new DataSourceLoader();
    }
//    @Bean
//    RedisTemplateManage redisTemplatManage() {
//        return  new RedisTemplateManage();
//    }
//    @Bean
//    RedisTemplateInjector redisTemplateInjector() {
//        return new RedisTemplateInjector();
//    }
    @Override
    public void afterPropertiesSet() throws Exception {
//        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext;
//        DataSourceConfig dataSourceConfig = applicationContext.getBean(DataSourceConfig.class);//dataSourceConfig();
//        Map<String, Supplier<DataSource>> dataSources = dataSourceConfig.toDataSources();
//
//        for (Map.Entry<String, Supplier<DataSource>> entry : dataSources.entrySet()) {
//            String datasourceName = entry.getKey();
//            Supplier<DataSource> dataSource = entry.getValue();
//
//            if (registry.containsBeanDefinition(datasourceName)) {
//                throw new RuntimeException("beanName 冲突："  + datasourceName +"[数据源名称与某Bean名称冲突、无法注册到IOC容器]");
//            }
//
//
//            BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(DataSourceFactory.class)
//                    .addConstructorArgValue(DataSource.class)
//                    .addConstructorArgValue(dataSource)
//                    .setLazyInit(true)
//                    .getBeanDefinition();
//            registry.registerBeanDefinition(datasourceName, beanDefinition);
//        }
//
//        for (Map.Entry<String, Redis> entry : dataSourceConfig.getRedis().entrySet()) {
//            String datasourceName = entry.getKey();
//            datasourceName = DBSourceUtils.getSourceName(datasourceName, "redis"); // datasourceName.redis
//            Redis redis = entry.getValue();
//            Supplier<Redis> redisSource = ()->redis;
//
//            if (registry.containsBeanDefinition(datasourceName)) {
//                throw new RuntimeException("beanName 冲突："  + datasourceName +"[数据源名称与某Bean名称冲突、无法注册到IOC容器]");
//            }
//            log.info("加载 Redis 数据源配置: {}", datasourceName);
//            BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(DataSourceFactory.class)
//                    .addConstructorArgValue(Redis.class)
//                    .addConstructorArgValue(redisSource)
//                    .setLazyInit(true)
//                    .getBeanDefinition();
//            registry.registerBeanDefinition(datasourceName, beanDefinition);
//        }

//        // 获取自定义 redis template 对象容器
//        RedisTemplateManage redisTemplateManage = applicationContext.getBean(RedisTemplateManage.class);
//        Map<String, RedisProperties> redisPropMap = dataSourceConfig.getRedisTemplate();
//
//        for (Map.Entry<String, RedisProperties> entry : redisPropMap.entrySet()) {
//            String datasourceName = entry.getKey();
//            datasourceName = DBSourceUtils.getSourceName(datasourceName, "multiRedisTemplate"); // datasourceName.redisTemplate
//            RedisProperties properties = entry.getValue();
//            LettuceConnectionFactory connectionFactory = LettuceUtils.createConnectionFactory(properties);
//
//            if (redisTemplateManage.containsName(datasourceName)) {
//                throw new RuntimeException("beanName 冲突："  + datasourceName +"[数据源名称与某Bean名称冲突、无法注册到定义对象容器]");
//            }
//
//            Supplier<RedisTemplate> redisSource = ()-> {
//                RedisTemplate template = new RedisTemplate();
//                template.setConnectionFactory(connectionFactory);
//                template.afterPropertiesSet();
//                return template;
//            };
//            redisTemplateManage.putRedisTemplate(datasourceName, redisSource);
//
//            Supplier<StringRedisTemplate> stringRedisSource = () -> new StringRedisTemplate(connectionFactory);
//            redisTemplateManage.putStringRedisTemplate(datasourceName, stringRedisSource);
//        }
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
